//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.jf.smali;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LiteralTools {
    private static Pattern specialFloatRegex = Pattern.compile("((-)?infinityf)|(nanf)", 2);
    private static Pattern specialDoubleRegex = Pattern.compile("((-)?infinityd?)|(nand?)", 2);

    public LiteralTools() {
    }

    public static byte parseByte(String byteLiteral) throws NumberFormatException {
        if (byteLiteral == null) {
            throw new NumberFormatException("string is null");
        } else if (byteLiteral.length() == 0) {
            throw new NumberFormatException("string is blank");
        } else {
            char[] byteChars;
            if (byteLiteral.toUpperCase().endsWith("T")) {
                byteChars = byteLiteral.substring(0, byteLiteral.length() - 1).toCharArray();
            } else {
                byteChars = byteLiteral.toCharArray();
            }

            int position = 0;
            int radix = 10;
            boolean negative = false;
            if (byteChars[position] == '-') {
                ++position;
                negative = true;
            }

            if (byteChars[position] == '0') {
                ++position;
                if (position == byteChars.length) {
                    return 0;
                }

                if (byteChars[position] != 'x' && byteChars[position] != 'X') {
                    if (Character.digit(byteChars[position], 8) >= 0) {
                        radix = 8;
                    }
                } else {
                    radix = 16;
                    ++position;
                }
            }

            byte result = 0;

            for(byte maxValue = (byte)(127 / (radix / 2)); position < byteChars.length; ++position) {
                int digit = Character.digit(byteChars[position], radix);
                if (digit < 0) {
                    throw new NumberFormatException("The string contains invalid an digit - '" + byteChars[position] + "'");
                }

                byte shiftedResult = (byte)(result * radix);
                if (result > maxValue) {
                    throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
                }

                if (shiftedResult < 0 && shiftedResult >= -digit) {
                    throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
                }

                result = (byte)(shiftedResult + digit);
            }

            if (negative) {
                if (result == -128) {
                    return result;
                } else if (result < 0) {
                    throw new NumberFormatException(byteLiteral + " cannot fit into a byte");
                } else {
                    return (byte)(result * -1);
                }
            } else {
                return result;
            }
        }
    }

    public static short parseShort(String shortLiteral) throws NumberFormatException {
        if (shortLiteral == null) {
            throw new NumberFormatException("string is null");
        } else if (shortLiteral.length() == 0) {
            throw new NumberFormatException("string is blank");
        } else {
            char[] shortChars;
            if (shortLiteral.toUpperCase().endsWith("S")) {
                shortChars = shortLiteral.substring(0, shortLiteral.length() - 1).toCharArray();
            } else {
                shortChars = shortLiteral.toCharArray();
            }

            int position = 0;
            int radix = 10;
            boolean negative = false;
            if (shortChars[position] == '-') {
                ++position;
                negative = true;
            }

            if (shortChars[position] == '0') {
                ++position;
                if (position == shortChars.length) {
                    return 0;
                }

                if (shortChars[position] != 'x' && shortChars[position] != 'X') {
                    if (Character.digit(shortChars[position], 8) >= 0) {
                        radix = 8;
                    }
                } else {
                    radix = 16;
                    ++position;
                }
            }

            short result = 0;

            for(short maxValue = (short)(32767 / (radix / 2)); position < shortChars.length; ++position) {
                int digit = Character.digit(shortChars[position], radix);
                if (digit < 0) {
                    throw new NumberFormatException("The string contains invalid an digit - '" + shortChars[position] + "'");
                }

                short shiftedResult = (short)(result * radix);
                if (result > maxValue) {
                    throw new NumberFormatException(shortLiteral + " cannot fit into a short");
                }

                if (shiftedResult < 0 && shiftedResult >= -digit) {
                    throw new NumberFormatException(shortLiteral + " cannot fit into a short");
                }

                result = (short)(shiftedResult + digit);
            }

            if (negative) {
                if (result == Short.MIN_VALUE) {
                    return result;
                } else if (result < 0) {
                    throw new NumberFormatException(shortLiteral + " cannot fit into a short");
                } else {
                    return (short)(result * -1);
                }
            } else {
                return result;
            }
        }
    }

    public static int parseInt(String intLiteral) throws NumberFormatException {
        if (intLiteral == null) {
            throw new NumberFormatException("string is null");
        } else if (intLiteral.length() == 0) {
            throw new NumberFormatException("string is blank");
        } else {
            char[] intChars = intLiteral.toCharArray();
            int position = 0;
            int radix = 10;
            boolean negative = false;
            if (intChars[position] == '-') {
                ++position;
                negative = true;
            }

            if (intChars[position] == '0') {
                ++position;
                if (position == intChars.length) {
                    return 0;
                }

                if (intChars[position] != 'x' && intChars[position] != 'X') {
                    if (Character.digit(intChars[position], 8) >= 0) {
                        radix = 8;
                    }
                } else {
                    radix = 16;
                    ++position;
                }
            }

            int result = 0;

            for(int maxValue = Integer.MAX_VALUE / (radix / 2); position < intChars.length; ++position) {
                int digit = Character.digit(intChars[position], radix);
                if (digit < 0) {
                    throw new NumberFormatException("The string contains an invalid digit - '" + intChars[position] + "'");
                }

                int shiftedResult = result * radix;
                if (result > maxValue) {
                    throw new NumberFormatException(intLiteral + " cannot fit into an int");
                }

                if (shiftedResult < 0 && shiftedResult >= -digit) {
                    throw new NumberFormatException(intLiteral + " cannot fit into an int");
                }

                result = shiftedResult + digit;
            }

            if (negative) {
                if (result == Integer.MIN_VALUE) {
                    return result;
                } else if (result < 0) {
                    throw new NumberFormatException(intLiteral + " cannot fit into an int");
                } else {
                    return result * -1;
                }
            } else {
                return result;
            }
        }
    }

    public static long parseLong(String longLiteral) throws NumberFormatException {
        if (longLiteral == null) {
            throw new NumberFormatException("string is null");
        } else if (longLiteral.length() == 0) {
            throw new NumberFormatException("string is blank");
        } else {
            char[] longChars;
            if (longLiteral.toUpperCase().endsWith("L")) {
                longChars = longLiteral.substring(0, longLiteral.length() - 1).toCharArray();
            } else {
                longChars = longLiteral.toCharArray();
            }

            int position = 0;
            int radix = 10;
            boolean negative = false;
            if (longChars[position] == '-') {
                ++position;
                negative = true;
            }

            if (longChars[position] == '0') {
                ++position;
                if (position == longChars.length) {
                    return 0L;
                }

                if (longChars[position] != 'x' && longChars[position] != 'X') {
                    if (Character.digit(longChars[position], 8) >= 0) {
                        radix = 8;
                    }
                } else {
                    radix = 16;
                    ++position;
                }
            }

            long result = 0L;

            for(long maxValue = Long.MAX_VALUE / (long)(radix / 2); position < longChars.length; ++position) {
                int digit = Character.digit(longChars[position], radix);
                if (digit < 0) {
                    throw new NumberFormatException("The string contains an invalid digit - '" + longChars[position] + "'");
                }

                long shiftedResult = result * (long)radix;
                if (result > maxValue) {
                    throw new NumberFormatException(longLiteral + " cannot fit into a long");
                }

                if (shiftedResult < 0L && shiftedResult >= (long)(-digit)) {
                    throw new NumberFormatException(longLiteral + " cannot fit into a long");
                }

                result = shiftedResult + (long)digit;
            }

            if (negative) {
                if (result == Long.MIN_VALUE) {
                    return result;
                } else if (result < 0L) {
                    throw new NumberFormatException(longLiteral + " cannot fit into a long");
                } else {
                    return result * -1L;
                }
            } else {
                return result;
            }
        }
    }

    public static float parseFloat(String floatString) {
        Matcher m = specialFloatRegex.matcher(floatString);
        if (m.matches()) {
            if (m.start(1) != -1) {
                return m.start(2) != -1 ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
            } else {
                return Float.NaN;
            }
        } else {
            return Float.parseFloat(floatString);
        }
    }

    public static double parseDouble(String doubleString) {
        Matcher m = specialDoubleRegex.matcher(doubleString);
        if (m.matches()) {
            if (m.start(1) != -1) {
                return m.start(2) != -1 ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
            } else {
                return Double.NaN;
            }
        } else {
            return Double.parseDouble(doubleString);
        }
    }

    public static byte[] longToBytes(long value) {
        byte[] bytes = new byte[8];

        for(int i = 0; value != 0L; ++i) {
            bytes[i] = (byte)((int)value);
            value >>>= 8;
        }

        return bytes;
    }

    public static byte[] intToBytes(int value) {
        byte[] bytes = new byte[4];

        for(int i = 0; value != 0; ++i) {
            bytes[i] = (byte)value;
            value >>>= 8;
        }

        return bytes;
    }

    public static byte[] shortToBytes(short value) {
        byte[] bytes = new byte[]{(byte)value, (byte)(value >>> 8)};
        return bytes;
    }

    public static byte[] floatToBytes(float value) {
        return intToBytes(Float.floatToRawIntBits(value));
    }

    public static byte[] doubleToBytes(double value) {
        return longToBytes(Double.doubleToRawLongBits(value));
    }

    public static byte[] charToBytes(char value) {
        return shortToBytes((short)value);
    }

    public static byte[] boolToBytes(boolean value) {
        return value ? new byte[]{1} : new byte[]{0};
    }

    public static void checkInt(long value) {
        if (value > -1L || value < -2147483648L) {
            throw new NumberFormatException(Long.toString(value) + " cannot fit into an int");
        }
    }

    public static void checkShort(long value) {
        if (value > 65535L | value < -32768L) {
            throw new NumberFormatException(Long.toString(value) + " cannot fit into a short");
        }
    }

    public static void checkByte(long value) {
        if (value > 255L | value < -128L) {
            throw new NumberFormatException(Long.toString(value) + " cannot fit into a byte");
        }
    }

    public static void checkNibble(long value) {
        if (value > 15L | value < -8L) {
            throw new NumberFormatException(Long.toString(value) + " cannot fit into a nibble");
        }
    }
}
